package com.n9.qq.android.login;

import com.n9.qq.util.Util;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.KeyAgreement;
import java.security.*;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;

/**
 * 共享key工厂
 * @author ice
 * @since 2019/1/29 16:48
 */
public class ShareKeyFactory {
    private static final Logger log = LoggerFactory.getLogger(ShareKeyFactory.class);
    /**
     * 生成shareKey
     * @param serverPubKeyData
     * @return
     */
    public static ShareKey generateBC(byte[] serverPubKeyData) {
        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC", "BC");
            ECGenParameterSpec parameterSpec = new ECGenParameterSpec("secp192k1");
            keyPairGenerator.initialize(parameterSpec);
            KeyPair cKeyPair = keyPairGenerator.genKeyPair();
            PrivateKey cPrvKey = cKeyPair.getPrivate();
            byte[] cPubKeyData = cKeyPair.getPublic().getEncoded();

            KeyFactory keyFactory = KeyFactory.getInstance("EC", "BC");
            PublicKey sPubKey = keyFactory.generatePublic(new X509EncodedKeySpec(serverPubKeyData));
            KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH", "BC");
            keyAgreement.init(cPrvKey);
            keyAgreement.doPhase(sPubKey, true);
            byte[] shareData = keyAgreement.generateSecret();

            byte[] shareTeaKey = DigestUtils.md5(shareData);

            byte[] clientPubKeyData = new byte[49];
            System.arraycopy(cPubKeyData, 23, clientPubKeyData, 0, 49);

            return new ShareKey(clientPubKeyData, shareTeaKey, cPrvKey);
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
        }
        return null;
    }


    /**
     * 计算shareKey
     * @param keyParam
     * @param pkcs8PrivateKey
     * @return
     */
    public static byte[] calcShareKey(byte[] keyParam, PrivateKey pkcs8PrivateKey) {
        byte[] shareKey = null;
        try {
            String keyPrev = keyParam.length < 30 ? "302E301006072A8648CE3D020106052B8104001F031A00" : "3046301006072A8648CE3D020106052B8104001F03320004";
            byte[] keyBytes = Util.convertHexStringToByteNoSpace(keyPrev + Util.convertByteToHexStringWithoutSpace(keyParam));
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
            PublicKey publicKey = KeyFactory.getInstance("EC", "BC").generatePublic(x509EncodedKeySpec);
            KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH", "BC");
            keyAgreement.init(pkcs8PrivateKey);
            keyAgreement.doPhase(publicKey, true);
            byte[] secret = keyAgreement.generateSecret();
            shareKey = DigestUtils.md5(secret);
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
        }
        return shareKey;
    }

    public static void main(String[] args) throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeySpecException {
        //30 2E 30 10 06 07 2A 86 48 CE 3D 02 01 06 05 2B 81 04 00 1F 03 1A 00 02 80 6E A1 23 D6 08 05 C3 80 23 2C AA 6C CC 53 62 4E 4A F0 67 95 43 C3 8B
        //04 92 8D 88 50 67 30 88 B3 43 26 4E 0C 6B AC B8 49 6D 69 77 99 F3 72 11 DE B2 5B B7 39 06 CB 08 9F EA 96 39 B4 E0 26 04 98 B5 1A 99 2D 50 81 3D A8
        PublicKey publicKey = KeyFactory.getInstance("EC", "BC").generatePublic(new X509EncodedKeySpec(Util.convertHexStringToByte("30 2E 30 10 06 07 2A 86 48 CE 3D 02 01 06 05 2B 81 04 00 1F 03 1A 00 02 80 6E A1 23 D6 08 05 C3 80 23 2C AA 6C CC 53 62 4E 4A F0 67 95 43 C3 8B")));

        System.out.println(Util.convertByteToHexString(publicKey.getEncoded()));

        PrivateKey privateKey = KeyFactory.getInstance("EC", "BC").generatePrivate(new X509EncodedKeySpec(Util.convertHexStringToByte("04 92 8D 88 50 67 30 88 B3 43 26 4E 0C 6B AC B8 49 6D 69 77 99 F3 72 11 DE B2 5B B7 39 06 CB 08 9F EA 96 39 B4 E0 26 04 98 B5 1A 99 2D 50 81 3D A8")));
        System.out.println(Util.convertByteToHexString(privateKey.getEncoded()));
    }

}
